package me.keiwu.admin.service.impl;


import com.alibaba.fastjson.JSON;
import me.keiwu.admin.domain.user.Label;
import me.keiwu.admin.domain.user.UserLabel;
import me.keiwu.admin.dao.UserLabelRepository;
import me.keiwu.admin.rpc.UserRpc;
import me.keiwu.admin.service.LabelService;
import me.keiwu.admin.service.UserLabelService;
import me.keiwu.admin.vo.UserLabelSearch;
import me.keiwu.pub.data.Response;
import me.keiwu.pub.data.service.UserInfoBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * Created by kei on 07/08/2017.
 */
@Service
@Transactional
public class
UserLabelServiceImpl implements UserLabelService {


    @Autowired
    private UserLabelRepository userLabelRepository;
    @Autowired
    private LabelService labelService;
    @Autowired
    private UserRpc userRpc;



    @Override
    public Long add(UserLabel userLabel) {
        userLabel.setCreatedBy("admin");
        userLabel.setCreatedDate(new Date());
        UserLabel dbUserLabel = userLabelRepository.save(userLabel);
        return dbUserLabel.getId();
    }

    @Override
    public boolean deleteByUserIdLabelId(Long userId, Long labelId) {
        userLabelRepository.deleteByUserIdLabelId(userId, labelId);
        return false;
    }

    @Override
    public Page<UserLabel> findLabel(UserLabelSearch userLabelSearch) {

        Page<UserLabel> page = this.list(userLabelSearch);

        for(UserLabel userLabel : page.getContent()){
            Label label = labelService.detail(userLabel.getLabelId());
            userLabel.setLabel(label);
        }

        return page;
    }

    @Override
    public Page<UserLabel> findUser(UserLabelSearch userLabelSearch) {

        Page<UserLabel> page = this.list(userLabelSearch);

        for(UserLabel userLabel : page.getContent()){
            UserInfoBean userInfo = JSON.parseObject(userRpc.userInfo(userLabel.getUserId()), UserInfoBean.class);
            userLabel.setUser(userInfo);
        }

        return page;
    }

    @Override
    public Page<UserInfoBean> findUserWithLabelId(Long labelId, int page, int size) {
        int total = userLabelRepository.countDistinctUserByLabelId(labelId);
        List<Long> idList = userLabelRepository.findDistinctUserByLabelId(labelId, size, size * page);
        List<UserInfoBean> userList = JSON.parseArray(userRpc.getUserList(JSON.toJSONString(idList)), UserInfoBean.class);
        userList = userList == null ? new ArrayList<>() : userList;
        Pageable pageable = new PageRequest(page, size);
        Page<UserInfoBean> infos = new PageImpl<>(userList, pageable, total);
        return infos;
    }

    @Override
    public Response findUserWithoutLabelId(Long labelId, String nickName, int page, int size) {
        List<Long> withoutList = userLabelRepository.findDistinctUserByLabelId(labelId);
        String users = userRpc.findWithoutUsers(JSON.toJSONString(withoutList), nickName, page, size);
        return Response.ok(JSON.parseObject(users));
    }


    @Override
    public int deleteByLabelId(Long id) {

        return userLabelRepository.deleteByLabelId(id);
    }

    private Page<UserLabel> list(UserLabelSearch userLabelSearch){
        Specification<UserLabel> spec;
        spec = (root, query, cb) -> {

            List<Predicate> predicateList = new ArrayList<Predicate>();
            if(userLabelSearch.getUserId() != null){
                Expression<Long> user_id = root.get("userId");
                predicateList.add(cb.equal(user_id, userLabelSearch.getUserId()));
            }
            if(userLabelSearch.getLabelId() != null){
                Expression<Long> label_id = root.get("labelId");
                predicateList.add(cb.equal(label_id, userLabelSearch.getLabelId()));
            }

            Predicate[] arrayPredicates = new Predicate[predicateList.size()];

            return cb.and(predicateList.toArray(arrayPredicates));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(userLabelSearch.getPage(), userLabelSearch.getSize(), sort);

        Page<UserLabel> pageResult= userLabelRepository.findAll(spec, pageable);

        return  pageResult;
    }


    @Override
    public Iterable<UserLabel> findAllUserLabel(Long userId) {

        Iterable<UserLabel> list = userLabelRepository.findAllByUserId(userId);

        for(UserLabel userLabel : list){
            Label label = labelService.detail(userLabel.getLabelId());
            userLabel.setLabel(label);
        }

        return list;
    }

}
